<?php
/*
 * @Author: your name
 * @Date: 2020-06-29 09:28:29
 * @LastEditTime: 2020-09-30 17:14:28
 * @LastEditors: 天羽落星辰
 * @Description: In User Settings Edit
 * @FilePath: \WWW\frx\application\api\controller\Index.php
 */

namespace app\api\controller;

use think\Db;
use app\admin\model\Bhd;
use app\common\library\Sms;
use app\common\controller\Api;
use app\admin\model\QianbaoSysetmLog;

/**
 * 我的资产
 */
class Wallet extends Api
{
    // protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['*'];

    /**
     * 我的资产首页
     */
    public function assets()
    {
        $data = [];
        // $this->auth->direct(120);
        $user = $this->auth->getuser();
        $currency = ['USDT','BLS'];
        // $currency = ['BLS'];
        // 更新资产
        foreach($currency as $v){
            $this->check_chongzhi($user,strtoupper($v));
        }

        
        // 模拟登陆更新数据
        // $this->auth->direct($user->id);
        // $user = $this->auth->getuser();
        $v = 'USDT';
        $data['assets'][0]['type'] = $v;
        $data['assets'][0]['available'] = $user[strtolower($v)] * 1;
        $data['assets'][0]['cny'] = bcmul(($user[strtolower($v)]),config('site.usdt_rmb'),2);

        $data['assets'][1]['type'] = 'BLS';
        $data['assets'][1]['available'] = $user['bls'] * 1;
        $data['assets'][1]['frozen'] = $user['bls_frozen'] * 1;
        $data['assets'][1]['cny'] = (bcmul(($user['bls_frozen']),config('site.usdt_rmb'),2) + bcmul(($user['bls']),config('site.usdt_rmb'),2))  / 10;

    

        // cny
        $data['cny'] = array_sum(array_column($data['assets'],'cny'));
        // dump(bcdiv($data['cny'] , 7,6));die;

        // usdt
        $data['usdt'] = bcdiv($data['cny'] , config('site.usdt_rmb'),6) * 1;
        $this->success('', $data);
    }
    /**
     * 充值
     * @param string $type  币种
     */
    public function recharge()
    {   
        $type = input('type');
        if(strtoupper($type) == 'BHD'){
            $this->error('请输入正确的币种');
            // $addr = config('BHD');
            // $data['code_img'] = request()->domain() . '/' . getcode(config('BHD'));
        }else{
            $addr = db('qianbao_sysetm_addr')->where('uid', $this->auth->id)->value('addr');
            $data['code_img'] = request()->domain() . '/' . getcode($addr);
        }
       
        $data['addr'] = $addr;

        $this->success('', $data);
    }

    /**
     * 币种列表
     */
    public function currency()
    {
        $category = db('token_category')->field('name')->where('pid', 0)->select();
        $this->success('', $category);
    }

    /**
     * 提币
     * @param string $type  币种
     */
    public function withdraw_money()
    {
        $type = $this->request->request("type");
        if (!$type) {
            $this->error('请输入参数');
        }
        $category = db('token_category')->field('id,name,min')->where('pid', 0)->where('name', strtoupper($type))->find();
        if (!$category) {
            $this->error('暂不可提币');
        }
        $service_charge = db('token_category')->field('id,service_charge,day')->where('status', 1)->where('pid', $category['id'])->order('day')->select();
        if (!$service_charge) {
            $this->error('暂不可提币');
        }
        foreach ($service_charge as &$v) {
            $v['service_charge'] = $v['service_charge'] * 1;
            $v['day'] = $v['day'].'天';
        }
        $category['service_charge'] = $service_charge;


        $this->success('', $category);
    }

    /**
     * 提币请求
     * @param string $type      币种
     * @param string $service_charge_id      手续费id
     * @param string $to      收款地址
     * @param string $money      提币数量
     * @param string $password      支付密码
     */
    public function withdraw_money_request()
    {
        $type = $this->request->request("type");
        $service_charge_id = $this->request->request("service_charge_id");
        $toaddr = $this->request->request("to");

        $money = abs($this->request->request("money"));
        $password = $this->request->request("password");
        // $code = $this->request->request("code");
        $user = $this->auth->getuser();


        // 手续费
        $charge = $this->service_charge($money, $type, $service_charge_id);


        // $ret = Sms::check($this->auth->mobile, $code, 'currency');
        // if (!$ret) {
        //     $this->error(__('验证码不正确'));
        // }

        if (md5($password) != $user['secpwd']) {
            $this->error('密码错误');
        }

        if (!$toaddr) {
            $this->error('地址不能为空');
        }
        if (strlen($toaddr) != 42) {
            $this->error('地址的位数不对');
        }


        $service_charge = db('token_category')->field('id,service_charge,day')->where('id', $service_charge_id)->where('status', 1)->find();



        $type = strtolower($type);


        $zt = 3;
        $usdt_automatic = config('site.usdt_money_automatic');
        if($money <= $usdt_automatic){
            $zt = 5;
            $note = '自动转账';
        }else{
            $note = '';
        }
        
        // 用户地址
        $addr = db('qianbao_sysetm_addr')->where('uid', $this->auth->id)->value('addr');
        Db::startTrans();
        try {
            db('user')->where('id', $this->auth->id)->lock(true)->count();
            $a1 = db('user')->where('id', $this->auth->id)->setDec($type, $money);
            $a2 = db('qianbao_sysetm_log')->insert([
                'uid' => $user['id'],
                'uname' => $user['username'],
                'bizhong' => $type,
                'addr' => $addr,
                'money' => - ($money - $charge),
                'charge' => $charge,
                'zt' => $zt,
                'before' => $user[$type],
                'after' => $user[$type] - $money,
                'type' => '2',
                'note' => $note,
                'memo' => '手续费' . ($service_charge['service_charge'] * 1) . '%, ' . $service_charge['day'] . '天内到账',
                'toaddr' => $toaddr,
                'createtime' => time(),
            ]);
            // dump($a2);die;
            if (!$a1 && !$a2) {
                throw new \Exception("提币失败");
            }
            // 提交事务
            Db::commit();
        } catch (\Exception $th) {
            // 回滚事务
            Db::rollback();
            $this->error(($th->getMessage()));
        }
        $this->success('已提交提币申请');
    }

    /**
     * 明细记录
     * @param string $currency    币种类型（默认usdt）
     * @param string $type    类型（1充值，2提币）默认显示全部
     * @param string $limit  页数列表显示条数
     * @param string $paging 页数
     */
    public function  withdraw_money_log()
    {
        $user = $this->auth->getuser();

        $bizhong = strtolower($this->request->request('currency'));
        $type = intval($this->request->request('type'));
        $limit = intval($this->request->request('limit'));
        $paging = intval($this->request->request('paging'));

        $bizhong = $bizhong ? $bizhong : 'usdt';
        $type = $type ? $type : '1,2';
        $limit = $limit ? $limit : 10;
        $paging = $paging ? 10 * $paging : 0;
        $data = [];

        $data = db('qianbao_sysetm_log')
            ->field('addr,zt,createtime,money,type,charge,hash,note')
            ->where('uid', $this->auth->id)
            ->where('bizhong', $bizhong)
            ->whereIn('type', $type)
            ->limit($paging, $limit) 
            ->order('id', 'desc')
            // ->fetchSql()
            ->select();
        if ($data) {
            foreach ($data as &$v) {
                $v['createtime'] = date('Y-m-d H:i', $v['createtime']);
                $v['money'] = round($v['money'], 2);
                // $v['addr'] = substr($v['addr'], 0, 9) . '...';
                $v['charge'] = $v['charge'] * 1;
            }
        }

        $this->success('', $data);
    }


    /**
     * @导入用户钱包: 
     * @ApiInternal
     * @return: bool
     */
    public  function wallet_user()
    {
        // 启动事务
        Db::startTrans();
        try {
            if (db('qianbao_sysetm_addr')->where('uid', $this->auth->id)->lock(true)->count()) {
                return false;
            } else {
                $ret = wallet_api();
                $data['addtime'] = time();
                $data['uid'] = $this->auth->id;
                $data['uname'] = $this->auth->username;
                $data['privatekey'] = $ret['PrivateKey'];
                $data['addr'] = $ret['address'];
                if (!db("qianbao_sysetm_addr")->insert($data)) {
                    throw new \Exception("钱包系统错误");
                }
            }
            // 提交事务
            Db::commit();
            return true;
        } catch (\Exception $e) {
            // 回滚事务
            Db::rollback();
            $this->error($e->getMessage());
        }
    }


    // 转账要求获取手续费
    private  function service_charge($money, $type, $service_charge_id)
    {
        if (!$type || !$service_charge_id) {
            $this->error('参数不正确');
        }
        $category = db('token_category')->field('id,name,min')->where('pid', 0)->where('name', strtoupper($type))->find();
        if (!$category) {
            $this->error('暂不可提币');
        }
        $service_charge = db('token_category')->field('id,service_charge,day')->where('id', $service_charge_id)->where('status', 1)->where('pid', $category['id'])->find();
        if (!$service_charge) {
            $this->error('暂不可提币');
        }
        $sxf = 0;
        if ($money < $category['min']) {
            $this->error('最低提币数量' . $category['min']);
        }
        // 手续费计算
        $sxf = $money * ($service_charge['service_charge'] / 100);
        $type = strtolower($type);

        if (empty($money) || $money == 0) {
            $this->error('请输入提币金额');
        } elseif (($money + $sxf) > $this->auth->$type) {
            $this->error('余额不足');
        }

        return $sxf;
    }

    /**
     * USDT全部收益列表
     * @param string $type  类型
     * @param string $limit  页数列表显示条数
     * @param string $paging 页数
     */
    public function index()
    {
        $type = intval($this->request->request('type'));
        $limit = intval($this->request->request('limit'));
        $paging = intval($this->request->request('paging'));
        $limit = $limit ? $limit : 10;
        $paging = $paging ? 10 * $paging : 0;
        if (!$type) {
            $data['count'] = $this->user_qianbao_sysetm_log_sum();
        }
        $type = $type ? $type : '4,5,6,7';

        $data['qianbao_sysetm_log'] = $this->user_qianbao_sysetm_log($type, $limit, $paging);


        $this->success('', $data);
    }

    // 我的收益总额
    private function user_qianbao_sysetm_log_sum()
    {
        $data = db('qianbao_sysetm_log')->field('type, money, createtime')
            ->where('uid', $this->auth->id)
            ->where('disable', 0)
            ->whereIn('type', '4,5,6,7')
            ->sum('money');

        return $data;
    }

    // 全部收益
    private function user_qianbao_sysetm_log($type, $limit, $paging)
    {
        $data = db('qianbao_sysetm_log')->field('type, money, createtime')
            ->where('uid', $this->auth->id)
            ->whereIn('type', $type)
            ->limit($paging, $limit)
            ->order('id desc')
            ->select();
        if ($data) {
            foreach ($data as &$v) {
                // $v['username'] = substr_replace($v['username'], '****', 3, 4); //2.替换字符串的子串
                $v['createtime'] = datetime($v['createtime']);
            }
        }

        return $data;
    }

    /**
     * 内网转账to
     * @param string $username  收款人用户名
     * @param string $money 金额
     * @param string $password 支付密码
     */
    public function lan_to()
    {
        $config = config('site');
        $username = $this->request->request("username");
        $money = $this->request->request("money");
        $password = $this->request->request("password");
        $user = $this->auth->getuser();

        if (md5($password) != $user['secpwd']) {
            $this->error('密码错误');
        }

        if ($this->auth->username == $username) {
            $this->error('不能转给自己');
        }

        $charge = 0;
        // 手续费计算
        $charge = $money * ($config['lan_usdt_cost'] / 100);


        if (empty($money) || $money == 0) {
            $this->error('转账金额不能为空');
        } elseif ($money > ($this->auth->usdt + $charge)) {
            $this->error('余额不足');
        }


        //用户名检测
        $touserinfo = userinfobyuname($username);
        if (!$touserinfo) {
            $this->error('转账对象不存在');
        } elseif ($touserinfo['status'] <> 'normal') {
            $this->error('转账对象账号异常');
        }
        $position = chickusposition($touserinfo, $user); //tou在u的位置

        //转账方向检测 可上下转，不可左右转
        if ($position == 'pang') {
            $this->error('转账对象不满足上下互转');
        }

        if ($money < $config['lan_usdt_min']) {
            $this->error('转账' . $config['lan_usdt_min'] . 'U起');
        }

        if ($money < $config['lan_usdt_min']) {
            $this->error('转账' . $config['lan_usdt_min'] . 'U起');
        }

        $type = 'usdt';
        

        // 启动事务
        Db::startTrans();
        try {
            db('user')->where('id', $this->auth->id)->lock(true)->count();
            $ouser = db('user')->field(true)->where('username', $username)->lock(true)->find();
            if (!$ouser) {
                throw new \Exception("该用户未注册");
            }
            $a1 = db('user')->where('id', $user['id'])->setDec($type, $money + $charge);
            $a2 = db('user')->where('id', $ouser['id'])->setInc($type, $money);
            $a3 = db('qianbao_sysetm_log')->insert([
                'uid' => $user['id'],
                'uname' => $user['username'],
                'bizhong' => $type,
                'money' => - $money,
                'charge' => $charge,
                'zt' => 1,
                'before' => $user[$type],
                'after' => $user[$type] - $money - $charge,
                'type' => 7,
                'memo' => '转账给'.$ouser['username'].'用户',
                'oid' => $ouser['id'],
                'ouname' => $ouser['username'],
                'createtime' => time(),
            ]);
            $a4 = db('qianbao_sysetm_log')->insert([
                'uid' => $ouser['id'],
                'uname' => $ouser['username'],
                'bizhong' => $type,
                'money' => $money - $charge,
                'charge' => 0,
                'zt' => 1,
                'before' => $ouser[$type],
                'after' => $ouser[$type] + $money - $charge,
                'type' => 7,
                'memo' => $user['username'].'用户转账给你',
                'oid' => $user['id'],
                'ouname' => $user['username'],
                'createtime' => time(),
            ]);
            if (!$a1 && !$a2 && !$a3 && !$a4) {
                throw new \Exception("转账失败");
            }
            // 提交事务
            Db::commit();
        } catch (\Exception $th) {
            // 回滚事务
            Db::rollback();
            $this->error(($th->getMessage()));
        }
        $this->success('转账成功');
    }


    /**
     * 币种兑换列表
     * @param string $type 币种
     */
    public function currency_switch_list()
    {
        $type = $this->request->request("type");
        $type = empty($type) ? 'usdt' : strtolower($type);
        $config = config('site');
        $bhd_price = db('rtp')->where('bizhong','BHD')->value('price');
        if($type == 'usdt'){
            $data[] = ['name' => 'TCC','cost' => $config['usdt_switch_tcc_cost'], 'ratio' => $config['usdt_to_tcc'] ];
            $data[] = ['name' => 'BHD','cost' => $config['usdt_switch_bhd_cost'], 'ratio' => round(1 / $bhd_price,6)];
        }elseif($type == 'bhd'){
            $data[] = ['name' => 'USDT','cost' => $config['usdt_switch_bhd_cost'], 'ratio' => $bhd_price * 1];
        }else{
            $this->error('该币种暂时无法兑换');
        }

        $this->success('',$data);
        
    }

    /**
     * 币种兑换提交
     * @param string $switch_top_type 兑换前币种
     * @param string $switch_top_money 兑换前金额
     * @param string $switch_after_type 兑换后币种
     */
    public function currency_switch()
    {       

        $config = config('site');
        
        $switch_top = strtolower($this->request->request("switch_top_type"));

        $switch_top_money = strtolower($this->request->request("switch_top_money"));
        $switch_after = strtolower($this->request->request("switch_after_type"));
        $score_to_usdt = config('site.score_to_usdt');
        $user = $this->auth->getuser();

        if(!$switch_top || !$switch_top_money || !$switch_after){
            $this->error('参数不正确');
        }

        try {
            if (empty($switch_top_money) || $switch_top_money == 0) {
                throw new \Exception('请输入兑换金额');
            } elseif ($switch_top_money > $user[$switch_top]) {
                throw new \Exception('你的余额不足');
            } 
        } catch (\Exception $th) {
            $this->error($th->getMessage());
        }


        // elseif ($switch_top_money < 99) {
        //     $this->error('单笔至少满99活力值');
        // }

        
        $bhd_price = db('rtp')->where('bizhong','BHD')->value('price');
        if($switch_top == 'bhd' && $switch_after == 'usdt'){
            // bhd兑换usdt
            $money = $switch_top_money * $bhd_price;
        }elseif($switch_top == 'usdt' && $switch_after == 'bhd'){
            // usdt兑换bhd
            $money = round($switch_top_money * round(1 / $bhd_price,6),6);
        }elseif($switch_top == 'usdt' && $switch_after == 'tcc'){
            // usdt兑换tcc
            $money = $switch_top_money * $config['usdt_to_tcc'];
        }else{
            $this->error('该币种暂时无法兑换'.strtoupper($switch_after));
        }

        // 手续费计算
        $charge = 0;
        if($switch_top == 'usdt' && $switch_after == 'tcc'){
            $charge = round($money * ($config['usdt_switch_tcc_cost'] / 100),6);
        }else{
            $charge = round($money * ($config['usdt_switch_bhd_cost'] / 100),6);
        }
        
        $memo = $switch_top_money.strtoupper($switch_top).'兑换'.($money - $charge).strtoupper($switch_after);
        // 启动事务
        Db::startTrans();
        try {
            db('user')->where('id', $this->auth->id)->lock(true)->count();
            $a1 = db('user')->where('id', $this->auth->id)->dec($switch_top, $switch_top_money)->inc($switch_after, ($money - $charge))->update();
            $a2 = db('qianbao_sysetm_log')->insert([
                'uid' => $user['id'],
                'uname' => $user['username'],
                'bizhong' => $switch_top,
                'money' => - $switch_top_money,
                'charge' => 0,
                'zt' => 1,
                'before' => $user[$switch_top],
                'after' => $user[$switch_top] - $switch_top_money,
                'type' => 6,
                'memo' => $memo,
                'createtime' => time(),
            ]);
            $a3 = db('qianbao_sysetm_log')->insert([
                'uid' => $user['id'],
                'uname' => $user['username'],
                'bizhong' => $switch_after,
                'money' => $money - $charge,
                'charge' => $charge,
                'zt' => 1,
                'before' => $user[$switch_after],
                'after' => $user[$switch_after] + $money - $charge,
                'type' => 6,
                'memo' => $memo,
                'createtime' => time(),
            ]);
            
            if (!$a1 && !$a2 && !$a3) {
                throw new \Exception("兑换失败");
            }
            // 提交事务
            Db::commit();
        } catch (\Exception $th) {
            // 回滚事务
            Db::rollback();
            $this->error(($th->getMessage()));
        }
        $this->success('兑换成功');
    }

    //检查用户某个币种是否充值到账并处理已优化
    private function check_chongzhi($user, $bizhong)
    {
        $bizhong = strtolower($bizhong);
        // 启动事务
        Db::startTrans();
        try {
            $data = [];
            // 链上最新余额
            $qianbao = db('qianbao_sysetm_addr')->where('uid', $user['id'])->lock(true)->find(); //行锁
            $ret = erc_yue($qianbao['addr'], $bizhong);

            if ($ret['zt'] == 1) {
                $yue_now = $ret['data'];
                if ($qianbao[$bizhong . '_last_num'] != $yue_now) {
                    if(!db('qianbao_sysetm_addr')->where('uid', $user['id'])->update([
                        $bizhong . '_last_num' => $yue_now,
                        $bizhong . '_last_time' => time(),
                    ])){
                        throw new \Exception("写入链上最新余额失败", 1);
                    }
                }
            }else{
                throw new \Exception("查询链上最新余额失败", 2);
            }
            $ret_erc = erctransactions($qianbao['addr'], $bizhong);
            // 时间排序，按正常充值顺序写入
            array_multisort($ret_erc, SORT_ASC, array_column($ret_erc, 'timeStamp'));


            // 查询符合要求未写入数据库的充值记录
            $i = 0;
            foreach ($ret_erc as $k => &$v) {
                if ($v['to'] == $qianbao['addr']) {
                    if ($v['value'] > 0) {
                        if (!db('qianbao_sysetm_log')->where('type',1)->where('hash', $v['hash'])->count()) {
                            $data[$i]['uid'] = $user['id'];
                            $data[$i]['uname'] = $user['username'];
                            $data[$i]['addr'] = $v['to'];
                            $data[$i]['hash'] = $v['hash'];
                            $data[$i]['toaddr'] = $v['from'];
                            $data[$i]['bizhong'] = strtolower($v['tokenSymbol']);
                            $data[$i]['money'] = bcdiv($v['value'], bcpow(10, $v['tokenDecimal']), $v['tokenDecimal']);
                            $data[$i]['memo'] = '充币成功';
                            $data[$i]['type'] = 1;
                            $data[$i]['zt'] = 1;
                            $data[$i]['money_lian'] = $yue_now; // 可能会有数据插入误差，但是是最新的链上余额
                            $data[$i]['time_cl'] = $v['timeStamp']; // 链上充值到账时间
                            $i++;
                        } else {
                            unset($v);
                        }
                    }
                }
            }

            if ($data) {
                // 为了同步金额变动优化
                $i = 0;
                foreach ($data as &$v) {
                    if ($i == 0) {
                        $v['before'] = $user[$v['bizhong']]; // 变动前余额
                        $v['after'] = $user[$v['bizhong']] + $v['money']; // 变动后余额
                    } else {
                        $v['before'] = $data[$i - 1]['after']; // 变动前余额
                        $v['after'] =  $v['before'] + $v['money']; // 变动后余额
                    }
                    $i++;
                }

                // 写入用户充值金额
                $value = array_sum(array_column($data, 'money'));
                if (!db('user')->where('id', $user['id'])->setInc($bizhong, $value)) {
                    throw new \Exception("写入用户充值金额失败", 3);
                }


                // 写入用户充值金额记录
                $qian_log = new QianbaoSysetmLog;
                if (!$qian_log->saveAll($data)) {
                    throw new \Exception("写入用户充值金额记录失败", 4);
                }
            }
            // 提交事务
            Db::commit();
        } catch (\Exception $th) {
            // 回滚事务
            Db::rollback();
            // $this->error($th->getCode());
            trace($th->getMessage(), '查询余额充值 error');
            return false;
            // $this->error('系统错误');
        }
        return true;
    }



    /**
     * 充值提交
     *
     * @param string $hash 充币地址
     * @param string $money 充值数量
     */
    public function add_submission()
    {   
        $hash = $this->request->request("hash");
        $money = $this->request->request("money");


        if(!$money){
            $this->error('请输入数量');
        }
        
        // $row = db('bhd')->where('uid',$this->auth->id)->where('hash',$hash)->whereIn('status','1,2')->count();

        // if($row){
        //     $this->error('请勿重复提交');
        // }

        $user = $this->auth->getuser();

        // $params['hash'] = $hash;
        $params['money'] = $money;
        $params['address'] = $user['address'];
        $params['uid'] = $user['id'];
        $params['uname'] = $user['username'];

        $model_bhd = new Bhd();
        $ret = $model_bhd->allowField(true)->save($params);
        if(!$ret){
            $this->error('提交失败');
        }
        $this->success('提交成功');
    }
}
